﻿#region imports

using System;
using System.Collections.Generic;
using System.Data.Services;
using System.Globalization;
using System.Linq;
using Codeplex.ODataTFS.Model.Entities;
using Codeplex.ODataTFS.Model.Serialization;
using Microsoft.Data.Services.Toolkit.QueryModel;

#endregion

namespace Codeplex.ODataTFS.Model.Repositories
{
	public class ChangeRepository
	{
		private readonly TFSChangeProxy _proxy;

		public ChangeRepository(TFSChangeProxy proxy)
		{
			_proxy = proxy;
		}

		public Change GetOne(string changeset, string path)
		{
			var changesetId = 0;
			if (!int.TryParse(changeset, NumberStyles.Integer, CultureInfo.InvariantCulture, out changesetId))
			{
				throw new ArgumentException("the changeset parameter must be numeric", "changeset");
			}

			return _proxy.GetChangesByChangeset(changesetId, 1).SingleOrDefault(c => c.Path.Equals(path, StringComparison.OrdinalIgnoreCase));
		}

		[RepositoryBehavior(HandlesTop = true)]
		public IEnumerable<Change> GetChangesByChangeset(ODataSelectManyQueryOperation operation)
		{
			var changesetId = 0;
			if (!int.TryParse(operation.Key, NumberStyles.Integer, CultureInfo.InvariantCulture, out changesetId))
			{
				throw new ArgumentException("The id parameter must be numeric", "id");
			}

			int topRequestValue = GetTopRequestValue(operation);

			return _proxy.GetChangesByChangeset(changesetId, topRequestValue);
		}

		public IEnumerable<Change> GetAll()
		{
			throw new DataServiceException(501, "Not Implemented", "The 'Change' collection cannot be enumerated as a root collection. It should depend on a Changeset. (e.g. /Changesets('12345')/Changes)", "en-US", null);
		}

		/// <summary>
		///     Gets the count treshold to minimize the number of elements retrieved from TFS
		/// </summary>
		private int GetTopRequestValue(ODataQueryOperation operation)
		{
			int topRequestValue = int.MaxValue;

			if (operation.IsCountRequest)
			{
				if (!string.IsNullOrEmpty(operation.ContinuationToken))
				{
					var parts = operation.ContinuationToken.Split(':').Select(int.Parse);
					topRequestValue = parts.First() + parts.Last() + 1;
				}
			}
			else
			{
				if (operation.TopCount > 0)
				{
					topRequestValue = operation.TopCount + operation.SkipCount + 1;
				}
			}

			return topRequestValue;
		}
	}
}
